home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / gnu / gnu_oleo_1_2_2.lha / oleo-1.2.2 / oleofile.c < prev    next >
C/C++ Source or Header  |  1993-03-03  |  19KB  |  942 lines

  1. /*    Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7.  
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU General Public License for more details.
  12.  
  13. You should have received a copy of the GNU General Public License
  14. along with this software; see the file COPYING.  If not, write to
  15. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  16.  
  17. /* this file was derived from the file sylk.c */
  18. #include "funcdef.h"
  19. #include <stdio.h>
  20. #include <ctype.h>
  21. #include "sysdef.h"
  22. #include "io-generic.h"
  23. #include "io-abstract.h"
  24. #include "io-utils.h"
  25. #include "io-term.h"
  26. #include "font.h"
  27. #include "global.h"
  28. #include "cell.h"
  29. #include "line.h"
  30. #include "sylk.h"
  31. #include "lists.h"
  32. #include "ref.h"
  33. #include "window.h"
  34.  
  35. extern char *bname[];
  36. extern default_jst;
  37. extern default_fmt;
  38. extern default_lock;
  39. extern unsigned short default_width;
  40.  
  41. extern struct rng all_rng;
  42. extern int a0;
  43.  
  44.  
  45. /* These functions read and write OLEO style files. */
  46.  
  47. void
  48. oleo_read_file (fp, ismerge)
  49.      FILE *fp;
  50.      int ismerge;
  51. {
  52.   char *ptr;
  53.   CELLREF crow = 0, ccol = 0, czrow = 0, czcol = 0;
  54.   int lineno;
  55.   char cbuf[1024];
  56.   char expbuf[1024];
  57.   char *vname, *vval;
  58.   int vlen = 0;
  59.   int cprot;
  60.   char *cexp, *cval;
  61.   CELL *cp;
  62.   struct rng rng;
  63.   int fmt = 0;
  64.   int jst = 0;
  65.   struct font_memo * fnt = 0;
  66.   struct font_memo ** fnt_map = 0;
  67.   int fnt_map_size = 0;
  68.   int fnt_map_alloc = 0;
  69.   int font_spec_in_format = 1;    /* Reset if we discover this is a v1.1 file. */
  70.   
  71.   long mx_row = MAX_ROW, mx_col = MAX_COL;
  72.   int old_a0;
  73.   int next_a0;
  74.  
  75.   old_a0 = a0;
  76.   next_a0 = old_a0;
  77.   a0 = 0;
  78.   lineno = 0;
  79.   if (!ismerge)
  80.     clear_spreadsheet ();
  81.   while (fgets (cbuf, sizeof (cbuf), fp))
  82.     {
  83.       lineno++;
  84.       if (lineno % 50 == 0)
  85.     io_info_msg ("Line %d", lineno);
  86.       if (ptr = (char *)index (cbuf, '\n'))
  87.     *ptr = '\0';
  88.  
  89.       ptr = cbuf;
  90.       switch (*ptr)
  91.     {
  92.     case '#':        /* comment line -- ignored */
  93.       break;
  94.     case '%':        /* Font or pixel size data. */
  95.       ptr++;
  96.       switch (*ptr)
  97.         {
  98.         case 'F':        /* %F font-name */
  99.           if (fnt_map_size == fnt_map_alloc)
  100.         {
  101.           fnt_map_alloc = (fnt_map_alloc + 1) * 2;
  102.           fnt_map =
  103.             ((struct font_memo **)
  104.              ck_remalloc
  105.              (fnt_map, fnt_map_alloc * sizeof (struct font_memo *)));
  106.         }
  107.           fnt_map[fnt_map_size++] = intern_font (ptr + 1);
  108.           break;
  109.         case 'f':        /* %f range font-name */
  110.           {
  111.         struct rng rng;
  112.         /* This field only occurs in files written by 1.1
  113.          * oleo.  It's presense indicates that when parsing
  114.          * format fields, we should *not* reset cell fonts to 0.
  115.          */
  116.         font_spec_in_format = 0;
  117.         ++ptr;
  118.         while (isspace (*ptr))
  119.           ++ptr;
  120.         if (!parse_cell_or_range (&ptr, &rng))
  121.           goto bad_field;
  122.         while (isspace (*ptr))
  123.           ++ptr;
  124.         set_area_font (&rng, intern_font (ptr));
  125.         break;
  126.           }
  127.         default:
  128.           goto bad_field;
  129.         }
  130.       break;
  131.     case 'F':        /* Format field */
  132.       vlen = 0;
  133.       ptr++;
  134.       fnt = 0;    /* The font must be explicitly overriden for a cell. */
  135.       while (*ptr)
  136.         {
  137.           if (*ptr != ';')
  138.         goto bad_field;
  139.           ptr++;
  140.           switch (*ptr++)
  141.         {
  142.           int clo, chi, cwid;
  143.         case 'C':    /* Column from rows 1 to 255 */
  144.           czcol = astol (&ptr);
  145.           vlen = 2;
  146.           break;
  147.  
  148.         case 'D':    /* Default format */
  149.           switch (*ptr++)
  150.             {
  151.             case 'G':
  152.               default_fmt = FMT_GEN - PRC_FLT;
  153.               break;
  154.             case 'E':
  155.               default_fmt = FMT_EXP - PRC_FLT;
  156.               break;
  157.             case 'F':
  158.               default_fmt = FMT_FXT - PRC_FLT;
  159.               break;
  160.             case '$':
  161.               default_fmt = FMT_DOL - PRC_FLT;
  162.               break;
  163.             case '*':    /* * format implemented as +- format */
  164.               default_fmt = FMT_GPH;
  165.               break;
  166.             case ',':    /* JF */
  167.               default_fmt = FMT_CMA - PRC_FLT;
  168.               break;
  169.             case 'U':
  170.               default_fmt = FMT_USR - PRC_FLT;
  171.               break;
  172.             case '%':
  173.               default_fmt = FMT_PCT - PRC_FLT;
  174.               break;
  175.             case 'H':
  176.               default_fmt = FMT_HID;
  177.               break;
  178.               /* End of JF */
  179.             default:
  180.               io_error_msg ("Line %d: format %c not supported", lineno, ptr[-1]);
  181.               break;
  182.             }
  183.           if (*ptr == 'F')
  184.             {
  185.               default_fmt += PRC_FLT;
  186.               ptr++;
  187.             }
  188.           else
  189.             default_fmt += astol (&ptr);
  190.           switch (*ptr++)
  191.             {
  192.             case 'C':
  193.               default_jst = JST_CNT;
  194.               break;
  195.             case 'L':
  196.               default_jst = JST_LFT;
  197.               break;
  198.             case 'R':
  199.               default_jst = JST_RGT;
  200.               break;
  201.             case 'G':    /* General format not supported */
  202.             default:
  203.               io_error_msg ("Line %d: Alignment %c not supported", lineno, ptr[-1]);
  204.               break;
  205.             }
  206.           default_width = astol (&ptr);
  207.           break;
  208.  
  209.         case 'f': /* Font specification */
  210.           {
  211.             int id;
  212.             id = astol(&ptr);
  213.             if (id < 0 || id >= fnt_map_size)
  214.               {
  215.             io_error_msg ("Line %d: Undefined font (%d)\n",
  216.                       lineno, id);
  217.             break;
  218.               }
  219.             fnt = fnt_map[id];
  220.             break;
  221.           }
  222.  
  223.         case 'F':
  224.           switch (*ptr++)
  225.             {
  226.             case 'D':
  227.               fmt = FMT_DEF;
  228.               break;
  229.             case 'G':
  230.               fmt = FMT_GEN - PRC_FLT;
  231.               break;
  232.             case 'E':
  233.               fmt = FMT_EXP - PRC_FLT;
  234.               break;
  235.             case 'F':
  236.               fmt = FMT_FXT - PRC_FLT;
  237.               break;
  238.             case '$':
  239.               fmt = FMT_DOL - PRC_FLT;
  240.               break;
  241.             case '*':    /* JF implemented as +- format */
  242.               fmt = FMT_GPH;
  243.               break;
  244.             case ',':    /* JF */
  245.               fmt = FMT_CMA - PRC_FLT;
  246.               break;
  247.             case 'U':
  248.               fmt = FMT_USR - PRC_FLT;
  249.               break;
  250.             case '%':
  251.               fmt = FMT_PCT - PRC_FLT;
  252.               break;
  253.             case 'H':
  254.               fmt = FMT_HID;
  255.               break;    /* END of JF */
  256.             case 'C':
  257.             default:
  258.               io_error_msg ("Line %d: format %c not supported", lineno, ptr[-1]);
  259.               fmt = FMT_DEF;
  260.               break;
  261.             }
  262.           if (*ptr == 'F')
  263.             {
  264.               fmt += PRC_FLT;
  265.               ptr++;
  266.             }
  267.           else
  268.             fmt += astol (&ptr);
  269.           switch (*ptr++)
  270.             {
  271.             case 'C':
  272.               jst = JST_CNT;
  273.               break;
  274.             case 'L':
  275.               jst = JST_LFT;
  276.               break;
  277.             case 'R':
  278.               jst = JST_RGT;
  279.               break;
  280.             case 'D':
  281.               jst = JST_DEF;
  282.               break;
  283.             default:
  284.               io_error_msg ("Line %d: Alignment %c not supported", lineno, ptr[-1]);
  285.               jst = JST_DEF;
  286.               break;
  287.             }
  288.           vlen = 1;
  289.           break;
  290.         case 'R':    /* Row from cols 1 to 63 */
  291.           czrow = astol (&ptr);
  292.           vlen = 4;
  293.           break;
  294.  
  295.         case 'W':    /* Width of clo to chi is cwid */
  296.           clo = astol (&ptr);
  297.           chi = astol (&ptr);
  298.           cwid = astol (&ptr) + 1;
  299.           for (; clo <= chi; clo++)
  300.             set_width (clo, cwid);
  301.           break;
  302.  
  303.         case 'H':    /* JF: extension */
  304.           clo = astol (&ptr);
  305.           chi = astol (&ptr);
  306.           cwid = astol (&ptr) + 1;
  307.           for (; clo <= chi; clo++)
  308.             set_height (clo, cwid);
  309.           break;
  310.         case 'c':
  311.           ccol = astol (&ptr);
  312.           break;
  313.         case 'r':
  314.           crow = astol (&ptr);
  315.           break;
  316.  
  317.         default:
  318.           goto bad_field;
  319.         }
  320.         }
  321.       switch (vlen)
  322.         {
  323.         case 1:
  324.           cp = find_or_make_cell (crow, ccol);
  325.           SET_FMT (cp, fmt);
  326.           SET_JST (cp, jst);
  327.           if (font_spec_in_format)
  328.         cp->cell_font = fnt;
  329.           break;
  330.         case 2:
  331.           rng.lr = MIN_ROW;
  332.           rng.lc = czcol;
  333.           rng.hr = mx_row;
  334.           rng.hc = czcol;
  335.           make_cells_in_range (&rng);
  336.           while (cp = next_cell_in_range ())
  337.         {
  338.           SET_FMT (cp, fmt);
  339.           SET_JST (cp, jst);
  340.           if (font_spec_in_format)
  341.             cp->cell_font = fnt;
  342.         }
  343.           break;
  344.         case 4:
  345.           rng.lr = czrow;
  346.           rng.lc = MIN_COL;
  347.           rng.hr = czrow;
  348.           rng.hc = mx_col;
  349.           make_cells_in_range (&rng);
  350.           while (cp = next_cell_in_range ())
  351.         {
  352.           SET_FMT (cp, fmt);
  353.           SET_JST (cp, jst);
  354.           if (font_spec_in_format)
  355.             cp->cell_font = fnt;
  356.         }
  357.           break;
  358.         default:
  359.           break;
  360.         }
  361.       break;
  362.  
  363.     case 'B':        /* Boundry field, ignored */
  364.       ptr++;
  365.       while (*ptr)
  366.         {
  367.           if (*ptr != ';')
  368.         goto bad_field;
  369.           ptr++;
  370.           switch (*ptr++)
  371.         {
  372.         case 'c':
  373.           mx_col = astol (&ptr);
  374.           if (mx_col > MAX_COL)
  375.             {
  376.               io_error_msg ("Boundry column %lu too large!", mx_col);
  377.               mx_col = MAX_COL;
  378.             }
  379.           break;
  380.         case 'r':
  381.           mx_row = astol (&ptr);
  382.           if (mx_row > MAX_ROW)
  383.             {
  384.               io_error_msg ("Boundry row %lu too large!", mx_row);
  385.               mx_row = MAX_ROW;
  386.             }
  387.           break;
  388.         default:
  389.           goto bad_field;
  390.         }
  391.         }
  392.       break;
  393.  
  394.     case 'N':        /* A Name field */
  395.       if (ptr[1] != 'N')
  396.         goto bad_field;
  397.       ptr += 2;
  398.       vname = 0;
  399.       vval = 0;
  400.       while (*ptr)
  401.         {
  402.           if (*ptr != ';')
  403.         goto bad_field;
  404.           *ptr++ = '\0';
  405.           switch (*ptr++)
  406.         {
  407.         case 'N':    /* Name is */
  408.           vname = ptr;
  409.           while (*ptr && *ptr != ';')
  410.             ptr++;
  411.           vlen = ptr - vname;
  412.           break;
  413.         case 'E':    /* Expression is */
  414.           vval = ptr;
  415.           while (*ptr && *ptr != ';')
  416.             ptr++;
  417.           break;
  418.         default:
  419.           --ptr;
  420.           goto bad_field;
  421.         }
  422.         }
  423.       if (!vname || !vval)
  424.         goto bad_field;
  425.       *ptr = '\0';
  426.       ptr = new_var_value (vname, vlen, vval);
  427.       if (ptr)
  428.         io_error_msg ("Line %d: Couldn't set %.*s to %s: %s", lineno, vlen, vname, vval, ptr);
  429.       break;
  430.  
  431.     case 'C':        /* A Cell entry */
  432.       cprot = 0;
  433.       cval = 0;
  434.       cexp = 0;
  435.       cval = 0;
  436.       ptr++;
  437.       while (*ptr)
  438.         {
  439.           int quotes;
  440.  
  441.           if (*ptr != ';')
  442.         goto bad_field;
  443.           *ptr++ = '\0';
  444.           switch (*ptr++)
  445.         {
  446.         case 'c':
  447.           ccol = astol (&ptr);
  448.           break;
  449.         case 'r':
  450.           crow = astol (&ptr);
  451.           break;
  452.         case 'R':
  453.           czrow = astol (&ptr);
  454.           break;
  455.         case 'C':
  456.           czcol = astol (&ptr);
  457.           break;
  458.         case 'P':    /* This cell is Protected */
  459.           cprot++;
  460.           break;
  461.         case 'K':    /* This cell's Konstant value */
  462.           cval = ptr;
  463.           quotes = 0;
  464.           while (*ptr && (*ptr != ';' || quotes > 0))
  465.             if (*ptr++ == '"')
  466.               quotes = !quotes;
  467.           break;
  468.         case 'E':    /* This cell's Expression */
  469.           cexp = ptr;
  470.           quotes = 0;
  471.           while (*ptr && (*ptr != ';' || quotes > 0))
  472.             if (*ptr++ == '"')
  473.               quotes = !quotes;
  474.  
  475.           break;
  476.         case 'G':
  477.           strcpy (expbuf, cval);
  478.           break;
  479.         case 'D':
  480.           strcpy (expbuf, cexp);
  481.           break;
  482.         case 'S':
  483.           cexp = expbuf;
  484.           break;
  485.         default:
  486.           --ptr;
  487.           goto bad_field;
  488.         }
  489.         }
  490.       *ptr = '\0';
  491.       if (cexp && cval && strcmp (cexp, cval))
  492.         {
  493.           ptr = read_new_value (crow, ccol, cexp, cval);
  494.           if (ptr)
  495.         {
  496.           io_error_msg ("Line %d: %d,%d: Read '%s' %s", lineno, crow, ccol, cexp, ptr);
  497.           break;
  498.         }
  499.         }
  500.       else if (cval)
  501.         {
  502.           ptr = read_new_value (crow, ccol, 0, cval);
  503.           if (ptr)
  504.         {
  505.           io_error_msg ("Line %d: %d,%d: Val '%s' %s", lineno, crow, ccol, cexp, ptr);
  506.           break;
  507.         }
  508.         }
  509.       else if (cexp)
  510.         {
  511.           ptr = read_new_value (crow, ccol, cexp, 0);
  512.           if (ptr)
  513.         {
  514.           io_error_msg ("Line %d: %d,%d: Exp '%s' %s", lineno, crow, ccol, cexp, ptr);
  515.           break;
  516.         }
  517.         }
  518.       if (cprot)
  519.         SET_LCK (find_or_make_cell (crow, ccol), LCK_LCK);
  520.       if (ismerge)
  521.         push_cell (crow, ccol);
  522.       /* ... */
  523.       break;
  524.     case 'E':
  525.       break;
  526.     case 'W':
  527.       io_read_window_config (ptr + 2);
  528.       break;
  529.     case 'U':
  530.       /* JF extension:  read user-defined formats */
  531.       read_mp_usr_fmt (ptr + 1);
  532.       break;
  533.       /* JF extension: read uset-settable options */
  534.     case 'O':
  535.       a0 = next_a0;
  536.       read_mp_options (ptr + 2);
  537.       next_a0 = a0;
  538.       a0 = 0;
  539.       break;
  540.     default:
  541.     bad_field:
  542.       a0 = old_a0;
  543.       if (!ismerge)
  544.         clear_spreadsheet ();
  545.       io_recenter_all_win ();
  546.       io_error_msg ("Line %d: Unknown OLEO line \"%s\"", lineno, cbuf);
  547.       return;
  548.     }
  549.     }
  550.   if (!feof (fp))
  551.     {
  552.       if (!ismerge)
  553.     clear_spreadsheet ();
  554.       io_recenter_all_win ();
  555.       io_error_msg ("read-file: read-error near line %d.", lineno);
  556.       return;
  557.     }
  558.   a0 = next_a0;
  559.   io_recenter_all_win ();
  560. }
  561.  
  562. static char *
  563. oleo_fmt_to_str (f1)
  564.      int f1;
  565. {
  566.   static char p_buf[40];
  567.   int p1;
  568.  
  569.   p_buf[1] = '\0';
  570.   switch (f1)
  571.     {
  572.     case FMT_DEF:
  573.       p_buf[0] = 'D';
  574.       break;
  575.     case FMT_HID:
  576.       p_buf[0] = 'H';
  577.       break;
  578.     case FMT_GPH:
  579.       p_buf[0] = '*';
  580.       break;
  581.     default:
  582.       p1 = GET_PRC (f1);
  583.       if (p1 == PRC_FLT)
  584.     {
  585.       p_buf[1] = 'F';
  586.       p_buf[2] = '\0';
  587.     }
  588.       else
  589.     sprintf (&p_buf[1], "%d", p1);
  590.       switch (f1 | PRC_FLT)
  591.     {
  592.     case FMT_USR:
  593.       p_buf[0] = 'U';
  594.       break;
  595.     case FMT_GEN:
  596.       p_buf[0] = 'G';
  597.       break;
  598.     case FMT_DOL:
  599.       p_buf[0] = '$';
  600.       break;
  601.     case FMT_PCT:
  602.       p_buf[0] = '%';
  603.       break;
  604.     case FMT_FXT:
  605.       p_buf[0] = 'F';
  606.       break;
  607.     case FMT_CMA:
  608.       p_buf[0] = ',';
  609.       break;
  610.     case FMT_EXP:
  611.       p_buf[0] = 'E';
  612.       break;
  613.     default:
  614.       p_buf[0] = '?';
  615.       break;
  616.     }
  617.       break;
  618.     }
  619.   return p_buf;
  620. }
  621.  
  622. static char
  623. jst_to_chr (just)
  624.      int just;
  625. {
  626.   switch (just)
  627.     {
  628.     case JST_DEF:
  629.       return 'D';
  630.     case JST_LFT:
  631.       return 'L';
  632.     case JST_RGT:
  633.       return 'R';
  634.     case JST_CNT:
  635.       return 'C';
  636.     default:
  637.       return '?';
  638.     }
  639. }
  640.  
  641. static FILE *oleo_fp;
  642. static struct rng *oleo_rng;
  643.  
  644. static void 
  645. oleo_write_var (name, var)
  646.      char *name;
  647.      struct var *var;
  648. {
  649.   if (var->var_flags
  650.       == VAR_UNDEF && (!var->var_ref_fm || var->var_ref_fm->refs_used == 0))
  651.     return;
  652.   switch (var->var_flags)
  653.     {
  654.     case VAR_UNDEF:
  655.       break;
  656.     case VAR_CELL:
  657.       if (var->v_rng.lr >= oleo_rng->lr && var->v_rng.lr <= oleo_rng->hr && var->v_rng.lc >= oleo_rng->lc && var->v_rng.lc <= oleo_rng->hc)
  658.     (void) fprintf (oleo_fp, "NN;N%s;E%s\n", var->var_name, cell_name (var->v_rng.lr, var->v_rng.lc));
  659.       break;
  660.     case VAR_RANGE:
  661.       if (var->v_rng.lr < oleo_rng->lr || var->v_rng.hr > oleo_rng->hr || var->v_rng.lc < oleo_rng->lc || var->v_rng.hc > oleo_rng->hc)
  662.     break;
  663.  
  664.       (void) fprintf (oleo_fp, "NN;N%s;E%s\n", var->var_name, range_name (&(var->v_rng)));
  665.       break;
  666. #ifdef TEST
  667.     default:
  668.       panic ("Unknown var type %d", var->var_flags);
  669. #endif
  670.     }
  671. }
  672.  
  673. static void
  674. write_mp_windows (fp)
  675.      FILE *fp;
  676. {
  677.   struct line line;
  678.   line.alloc = 0;
  679.   line.buf = 0;
  680.   io_write_window_config (&line);
  681.   fputs (line.buf, fp);
  682.   free (line.buf);
  683. }
  684.  
  685. void
  686. oleo_write_file (fp, rng)
  687.      FILE *fp;
  688.      struct rng *rng;
  689. {
  690.   CELLREF r, c;
  691.   CELL *cp;
  692.   CELLREF crow = 0, ccol = 0;
  693.   unsigned short w;
  694.   /* struct var *var; */
  695.   int old_a0;
  696.   int fnt_map_size = 0;
  697.  
  698.   (void) fprintf (fp, "# This file was created by GNU Oleo\n");
  699.  
  700.   /* All versions of the oleo file format should have a 
  701.    * version cookie on the second line.
  702.    */
  703.   (void) fprintf (fp, "# format 1.0\n");
  704.  
  705.   /* If no range given, write the entire file */
  706.   if (!rng)
  707.     {
  708.       int n;
  709.       int fmts;
  710.       char *data[9];
  711.  
  712.       rng = &all_rng;
  713.  
  714.       (void) fprintf (fp, "F;D%s%c%u\n", oleo_fmt_to_str (default_fmt), jst_to_chr (default_jst), default_width);
  715.  
  716.       fmts = usr_set_fmts ();
  717.       for (n = 0; n < 16; n++)
  718.     {
  719.       if (fmts & (1 << n))
  720.         {
  721.           get_usr_stats (n, data);
  722.           fprintf (fp, "U;N%u;P%s;S%s", n + 1, data[7], data[8]);
  723.           if (data[0][0])
  724.         fprintf (fp, ";HP%s", data[0]);
  725.           if (data[1][0])
  726.         fprintf (fp, ";HN%s", data[1]);
  727.           if (data[2][0])
  728.         fprintf (fp, ";TP%s", data[2]);
  729.           if (data[3][0])
  730.         fprintf (fp, ";TN%s", data[3]);
  731.           if (data[4][0])
  732.         fprintf (fp, ";Z%s", data[4]);
  733.           if (data[5][0])
  734.         fprintf (fp, ";C%s", data[5]);
  735.           if (data[6])
  736.         fprintf (fp, ";D%s", data[6]);
  737.           putc ('\n', fp);
  738.         }
  739.     }
  740.       write_mp_options (fp);
  741.     }
  742.  
  743.   old_a0 = a0;
  744.   a0 = 0;
  745.  
  746.   find_widths (rng->lc, rng->hc);
  747.   w = next_width (&c);
  748.   while (w)
  749.     {
  750.       CELLREF cc, ccc;
  751.       unsigned short ww;
  752.       cc = c;
  753.       do
  754.     ww = next_width (&ccc);
  755.       while (ccc == ++cc && ww == w);
  756.       (void) fprintf (fp, "F;W%u %u %u\n", c, cc - 1, w - 1);
  757.       c = ccc;
  758.       w = ww;
  759.     }
  760.  
  761.   find_heights (rng->lr, rng->hr);
  762.   w = next_height (&r);
  763.   while (w)
  764.     {
  765.       CELLREF rr, rrr;
  766.       unsigned short ww;
  767.  
  768.       rr = r;
  769.       do
  770.     ww = next_height (&rrr);
  771.       while (rrr == ++rr && ww == w);
  772.       (void) fprintf (fp, "F;H%u %u %u\n", r, rr - 1, w - 1);
  773.       r = rrr;
  774.       w = ww;
  775.     }
  776.  
  777.   oleo_fp = fp;
  778.   oleo_rng = rng;
  779.   for_all_vars (oleo_write_var);
  780.   find_cells_in_range (rng);
  781.  
  782.   {
  783.     struct font_memo * fm;
  784.     for (fm = font_list; fm; fm = fm->next)
  785.       fm->id_memo = -1;
  786.   }
  787.   while (cp = next_row_col_in_range (&r, &c))
  788.     {
  789.       char *ptr;
  790.       int f1, j1;
  791.       char p_buf[40];
  792.  
  793.       f1 = GET_FMT (cp);
  794.       j1 = GET_JST (cp);
  795.       if (f1 != FMT_DEF || j1 != JST_DEF || cp->cell_font)
  796.     {
  797.       if (cp->cell_font)
  798.         {
  799.           if (cp->cell_font->id_memo < 0)
  800.         {
  801.           cp->cell_font->id_memo = fnt_map_size++;
  802.           fprintf (fp, "%%F%s,%s,%f\n",
  803.                cp->cell_font->name, cp->cell_font->psname,
  804.                cp->cell_font->scale);
  805.         }
  806.         }
  807.       (void) fprintf (fp, "F;");
  808.       if (c != ccol)
  809.         {
  810.           (void) fprintf (fp, "c%u;", c);
  811.           ccol = c;
  812.         }
  813.       if (r != crow)
  814.         {
  815.           (void) fprintf (fp, "r%u;", r);
  816.           crow = r;
  817.         }
  818.       if (cp->cell_font)
  819.         (void) fprintf (fp, "f%d;", cp->cell_font->id_memo);
  820.       (void) fprintf (fp, "F%s%c\n",
  821.               oleo_fmt_to_str (f1), jst_to_chr (j1));
  822.     }
  823.  
  824.       if (!GET_TYP (cp) && !cp->cell_formula)
  825.     continue;
  826.  
  827.       (void) fprintf (fp, "C;");
  828.       if (c != ccol)
  829.     {
  830.       (void) fprintf (fp, "c%u;", c);
  831.       ccol = c;
  832.     }
  833.       if (r != crow)
  834.     {
  835.       (void) fprintf (fp, "r%u;", r);
  836.       crow = r;
  837.     }
  838.  
  839.       if (cp->cell_formula)
  840.     {
  841.       (void) fprintf (fp, "E%s", decomp (r, c, cp));
  842.       decomp_free ();
  843.     }
  844.  
  845.       switch (GET_TYP (cp))
  846.     {
  847.     case 0:
  848.       ptr = 0;
  849.       break;
  850.     case TYP_STR:
  851.       ptr = 0;
  852.       if (cp->cell_formula)
  853.         putc (';', fp);
  854.       (void) fprintf (fp, "K\"%s\"", cp->cell_str);
  855.       break;
  856.     case TYP_FLT:
  857.       ptr = flt_to_str (cp->cell_flt);
  858.       break;
  859.     case TYP_INT:
  860.       sprintf (p_buf, "%ld", cp->cell_int);
  861.       ptr = p_buf;
  862.       break;
  863.     case TYP_BOL:
  864.       ptr = bname[cp->cell_bol];
  865.       break;
  866.     case TYP_ERR:
  867.       ptr = ename[cp->cell_err];
  868.       break;
  869. #ifdef TEST
  870.     default:
  871.       ptr = 0;
  872.       panic ("What cell type %d", GET_TYP (cp));
  873. #endif
  874.     }
  875.  
  876.       if (ptr)
  877.     {
  878.       if (cp->cell_formula)
  879.         putc (';', fp);
  880.       (void) fprintf (fp, "K%s", ptr);
  881.     }
  882.       if (GET_LCK (cp) == LCK_LCK)
  883.     (void) fprintf (fp, ";P");
  884.  
  885.       putc ('\n', fp);
  886.     }
  887.  
  888.   if (rng == &all_rng)
  889.     write_mp_windows (fp);
  890.  
  891.   (void) fprintf (fp, "E\n");
  892.   a0 = old_a0;
  893. }
  894.  
  895. int
  896. oleo_set_options
  897.   (set_opt, option)
  898.      int set_opt;
  899.      char *option;
  900. {
  901.   return -1;
  902. }
  903.  
  904. void
  905. oleo_show_options ()
  906. {
  907.   io_text_line ("File format: oleo.");
  908. }
  909.  
  910.  
  911. #if 0
  912. This was used in releases 1.0 and 1.1 to write fonts.  
  913. It is no longer used but is kept here for reference since 1.2 and later
  914. versions should continue to understand the older file format for a while.
  915.  
  916. static int
  917. oleo_write_fonts (rng, font, ignore)
  918.      struct rng *rng;
  919.      struct font_memo *font;
  920.      void *ignore;
  921. {
  922.   struct rng r;
  923.   char *rname;
  924.   r = *rng;
  925.   if (r.lr < oleo_rng->lr)
  926.     r.lr = oleo_rng->lr;
  927.   if (r.lc < oleo_rng->lc)
  928.     r.lc = oleo_rng->lc;
  929.   if (r.hr > oleo_rng->hr)
  930.     r.hr = oleo_rng->hr;
  931.   if (r.hc > oleo_rng->hc)
  932.     r.hc = oleo_rng->hc;
  933.   rname = range_name (&r);
  934.   fprintf (oleo_fp, "%%f %s %s,%s,%f\n",
  935.        rname, font->name, font->psname, font->scale);
  936.   return 1;
  937. }
  938.  
  939.  
  940. #endif
  941.  
  942.